/*
		* Author:	 Sander
		* Date:		 12-apr-2011
		* Name:		 Sphere
		* Version:	1.0
		*
		* This code is property of Sander blahblahblah copyright blahblah.
*/


package javaraytracer.Objects;

import javaraytracer.IntersectionInfo;
import javaraytracer.Materials.Material;
import javaraytracer.Ray;
import javaraytracer.Vec3;

//PENDING:add function/property description
public class Sphere extends Traceable
{

	public Vec3 origin;
	public float radius;
	private double t1 = 0.0;
	private double t2 = 0.0;

	public Sphere(Vec3 o, float r, Material m)
	{
		//print(this);
		origin = o;
		radius = r;
		material = m;
	}

	public IntersectionInfo intersect( Ray r )
	{
		t1 = 0.0;
		t2 = 0.0;

		double a = r.direction.dot( r.direction );
		Vec3 ray = r.origin.sub( origin );
		double b = 2 * (ray.dot( r.direction ) );

		double c = ray.dot( ray ) - (radius * radius);

		double D = (b * b) - (4.0 * a * c);
		if(D < 0)
		{
			return new IntersectionInfo(false);
		}

		if (D == 0.0)
		{
			t1 = -b / (2.0 * a);

		}
		else if (D > 0)
		{
			t1 = (-b - Math.sqrt( D )) / (2.0 * a);
			t2 = (-b + Math.sqrt( D )) / (2.0 * a);
		}
		if(t1 > t2)
		{
			t1 = t2;
		}
		if (t1 > 0)
		{
			Vec3 location = r.origin.add(r.direction.mul(t1));
			Vec3 normal = new Vec3( location.x - origin.x, location.y - origin.y, location.z - origin.z);
			normal.normalize();

			double distance = location.sub( r.origin ).length();
			IntersectionInfo ii = new IntersectionInfo( location, normal, (float)distance, this );
			return ii;
		}
		else
		{
			return new IntersectionInfo(false) ;
		}
	}

	public boolean hit( Ray r )
	{
		
		t1 = 0.0;
		t2 = 0.0;
		
		double A = r.direction.dot(r.direction);

		Vec3 ray = r.origin.sub( this.origin );
		double B = 2 * (ray.dot( r.direction ));

		double C = ray.dot( ray ) - (radius * radius);

		double D = (B * B) - (4.0 * A * C);

		if(D == 0)
		{
			t1 = -B / (2.0 * A);
			if(t1 >= 0.0 && t1 <= 1.0)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else if(D > 0)
		{
			t1 = (-B - Math.sqrt( D )) / (2.0 * A);
			t2 = (-B + Math.sqrt( D )) / (2.0 * A);

			if (t1 >= 0 && t1 <= 1)
			{
				return true;
			}
			else if(t2 >= 0 && t2 <= 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}

	public Material getMaterial()
	{
		return material;
	}

	public Material getMaterial(IntersectionInfo info)
	{
		material.position(info);
		return material;
	}

}
